<template>
  <div class="form-js-control">
    <el-button type="plain-third" plain @click="onRunJs(true)" :loading="loading">
      <i :class="[ isSuccess ? 'el-icon-circle-check':'el-icon-circle-close']" v-if="!loading && isRun"></i>
      {{ $t('formSetting.jsCodeBlock.runText') }}
    </el-button>
  </div>
</template>
<script>
import FormMixin from '@src/component/form/mixin/form';
import { isObjectString, executeCode, matchFormField } from './model/index';
import {FieldTypeMappingEnum} from "@model/enum/FieldMappingEnum";
import { isString } from "lodash";
import { isInSubForm } from '@src/component/form/util/index';
import { uuid } from 'pub-bbx-utils';
export default {
  name: 'form-js-control',
  mixins: [FormMixin],
  props: {
    value: {
      type: String,
      default: ''
    },
    formAllValue: {
      type: Object,
      default: ()=> null
    },
    formAllFields: {
      type: Array,
      default: ()=> ([])
    },
    inLineTable: {
      type: Boolean,
      default: ()=> false
    }
  },
  data() {
    return {
      isRun: false, // 是否已经运行
      isSuccess: false, // 是否运行成功
      loading: false,
    };
  },
  computed: {
    /* 是否自动运行 */
    isAutomaticOperation() {
      return this.field.setting?.automaticOperation || 0;
    },
    /* 是否开启自动校验*/
    automaticCheck() {
      return this.field.setting?.automaticCheck || 0;
    },
    /* 代码块配置 */
    codeBlockConfig() {
      return this.field.setting?.codeBlockConfig || {};
    },
    isHidden() {
      return this.field.setting?.hidden || false;
    },
    /* 是否在子表单中 */
    isInSubForm() {
      return isInSubForm(this.field);
    },
    currentFormAllValue() {
      return this.formAllValue || this.formValue
    },
    currentFormAllFields() {
      if(this.formAllFields.length) return this.formAllFields
      return this.fields
    }
  },
  mounted() {
    // 表单中隐藏该字段
    if(this.isHidden && !this.inLineTable) {
      this.$parent.$el.style.display = 'none';
    }

    // 自动运行代码块
    if(this.isAutomaticOperation) {
      const forceUpdate = this.isInSubForm // 子表单每次加载强制更新
      this.onRunJs(true);
    }
  },
  methods: {
    /* js代码块运行结果*/
    async jsCodeRunResult(forceUpdate = false) {
      const codeContent = this.codeBlockConfig?.codeContent || '';
      return await executeCode(codeContent, this.currentFormAllValue, this.field, forceUpdate, {fields: this.currentFormAllFields, formInstance: this.formBuilderComponent});
    },
    /* 运行js代码块 */
    async onRunJs(forceUpdate = false) {
      this.loading = true;
      this.isRun = true;
      const runJsCodeResult = await this.jsCodeRunResult(forceUpdate);
      if(!isObjectString(runJsCodeResult)){
        this.loading = false;
        this.$message.warning(this.$t('formSetting.jsCodeBlock.runErrorMsg'));
        return;
      }
      this.inputForValue(await this.jsCodeRunResult());
      this.matchForm();
    },
    getDataType(data) {
      const typeString = Object.prototype.toString.call(data).split(' ')[1];
      return typeString.slice(0, typeString.length - 1);
    },
    /* 匹配校验相关的表单值 */
    async matchForm() {
      const matchFormFields = matchFormField(this.field, this.currentFormAllFields);
      if (!await this.jsCodeRunResult()) return this.isFailed();
      let value = JSON.parse(await this.jsCodeRunResult());
      // if(matchFormFields.length == 0){
      //   return this.isFailed();
      // }
      try {
        if (matchFormFields.length > 0) {
          for (let i = 0; i < matchFormFields.length; i++) {
            const f = matchFormFields[i];

            const {relatedCodeTemplate = {}} = f.setting || {};
            const aliasPath = relatedCodeTemplate.aliasPath.replace('$.', '');
            // if(isNaN(value[aliasPath]) && f.formType !== 'select') {
            //   return this.isFailed();
            // }
            // const isSelectFormType = f.formType === 'select';
            // const isValueArray = isArray(value[aliasPath]);
            // if((isSelectFormType && isValueArray) || (!isSelectFormType && !isValueArray)){
            let beSetValue = value[aliasPath];
            // 下拉菜单处理
            if (f.formType === FieldTypeMappingEnum.Select) {
              if (!Array.isArray(beSetValue)) return this.isFailed(this.$t('formSetting.jsCodeBlock.typeNotSame', {
                defaultType: this.getDataType(beSetValue),
                toType: 'Array'
              }));
              const field = this.currentFormAllFields.find(field => field.fieldName === f.fieldName);
              if (field) {
                field.setting.dataSource = [...beSetValue];

              }
            } else {
              if (!isString(beSetValue) && f.formType !== FieldTypeMappingEnum.Number) {
              // beSetValue = JSON.stringify(beSetValue);
                return this.isFailed(this.$t('formSetting.jsCodeBlock.typeNotSame', {
                  defaultType: this.getDataType(beSetValue),
                  toType: 'String'
                }));
              }
              this.currentFormAllValue[f.fieldName] = beSetValue;
            }
          }
        }
      } catch (e) {
        return this.isFailed(e);
      }

      this.isSuccess = true;
      setTimeout(()=>{ this.loading = false; },100);
    },
    isFailed(msg) {
      this.isSuccess = false;
      const displayName = this.field.displayNameLanguage?.[this.$i18n.locale] || this.field.displayName;
      this.$message.warning(`${this.$t('formSetting.jsCodeBlock.runFailed',{displayName})}${msg ? ',' + msg : ''}`);
      setTimeout(()=>{ this.loading = false; },100);
    }
  },

};
</script>
<style lang="scss" scoped>
.form-js-control {
    button {
      width: 80px;
      .el-icon-circle-close {
        color: $color-danger;
      }
      .el-icon-circle-check{
        color: $color-main;
      }
    }
}

</style>
